package com.baor.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baor.dao.RoleMenuDao;
import com.baor.dao.UserDao;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baor.dao.MenuDao;
import com.baor.domain.*;
import com.baor.utils.AjaxResult;
import com.baor.utils.RedisUtil;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import com.baor.service.UserService;
import com.baor.security.TokenService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

import static com.baor.utils.DateUtil.now;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private RoleMenuDao roleMenuDao;
    @Value("${sys.default.pwd}")
    private String defaultPwd;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;


    @Override
    public AjaxResult<?> insertUser(UserVo vo) {
        LambdaQueryWrapper<UserVo> lqw = new LambdaQueryWrapper<>();
        lqw.eq(UserVo::getUserAccount, vo.getUserAccount());
        UserVo userVo = userDao.selectOne(lqw);
        if ( userVo != null ){
            return AjaxResult.error("添加失败，该账号已存在");
        }
        vo.setUserCreatetime(now());
        if ( vo.getUserPwd() == null || "".equals(vo.getUserPwd())){
            vo.setUserPwd(passwordEncoder.encode(defaultPwd));
        }
        vo.setUserPwd(passwordEncoder.encode(vo.getUserPwd()));
        return userDao.insert(vo) > 0 ? AjaxResult.success() : AjaxResult.error("操作失败") ;
    }

    @Override
    public AjaxResult<?> userInfo(Integer userId) {
        return AjaxResult.success(userDao.selectById(userId));
    }

    @Override
    public AjaxResult<?> update(UserVo vo) {
       if(vo.getUserPwd() == null && "".equals(vo.getUserPwd())){
           vo.setUserPwd(passwordEncoder.encode(vo.getUserPwd()));
       }
       return AjaxResult.success(userDao.updateById(vo));
    }

    @Override
    public AjaxResult<?> delete(Integer userId) {
        return userDao.deleteById(userId) > 0 ? AjaxResult.success() : AjaxResult.error("删除失败");
    }

    @Override
    public AjaxResult<?> resetPwd(Integer userId) {
        UserVo vo = new UserVo();
        vo.setUserId(userId);
        vo.setUserPwd(passwordEncoder.encode(defaultPwd));
        return userDao.updateById(vo) > 0 ? AjaxResult.success() : AjaxResult.error("重置失败");
    }

    @Override
    public AjaxResult<?> userList(UserVo vo) {
        Page<UserVo> page = null;
        if(vo != null && vo.getPageSize() != null){
            page = new Page<>(vo.getPageIndex(),vo.getPageSize());
        }else{
            page = new Page<>(1, 10);
        }
        if ( vo == null )
            vo = new UserVo();
        MPJLambdaWrapper<UserVo> lqw = new MPJLambdaWrapper<>();
        lqw.select(UserVo.class, x -> !x.getColumn().equals("user_role"))
                .select(UserVo::getUserId)
                .leftJoin(RoleVo.class, RoleVo::getRoleId, UserVo::getUserRole)
                .selectAs(RoleVo::getRoleName, "user_role")
                .notIn(UserVo::getUserRole, 1);
        if ( !"".equals(vo.getUserName()) && vo.getUserName() != null ){
            lqw.like(UserVo::getUserName,vo.getUserName());
        }
        if ( !"".equals(vo.getUserAccount()) && vo.getUserAccount() != null )
            lqw.like(UserVo::getUserAccount,vo.getUserAccount());
        List<UserVo> list = userDao.selectPage(page,lqw).getRecords();
        list.forEach(x -> x.setUserPwd(null) );
        Map<String,Object> map = new HashMap<>();
        map.put("list", list);
       map.put("pageCount", userDao.selectPage(page,lqw).getPages());
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult<?> login(UserVo userVo) {
        System.out.println("login-info:"+userVo);
        Authentication authentication = null;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(userVo.getUserAccount(),userVo.getUserPwd())
            );
        } catch (RuntimeException ex) {
            System.out.println("出异常了");
            ex.printStackTrace();
            return AjaxResult.error();
        }
        Map<String,Object> res = new HashMap<>();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        UserVo vo = loginUser.getUserVo();
        String token = tokenService.createToken(vo);
        redisUtil.setValue("userAccount:"+vo.getUserAccount(),loginUser);
        redisUtil.setValue("loginUser:"+loginUser,token);
        res.put("authorization",token);
        res.put("user", vo);
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, loginUser.getPassword(), loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        return AjaxResult.success(res);
    }

    @Override
    public UserVo selectUserByUserName(String username) {
        return userDao.selectUserByUserName(username);
    }


}
